home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / beav_132 / part03 / basic.c next >
C/C++ Source or Header  |  1991-11-13  |  12KB  |  541 lines

  1. /*
  2. *      Basic cursor motion commands.
  3. * The routines in this file are the basic
  4. * command functions for moving the cursor around on
  5. * the screen, setting mark, and swapping dot with
  6. * mark. Only moves between lines, which might make the
  7. * current buffer framing bad, are hard.
  8. */
  9.  
  10. #include    "def.h"
  11.  
  12. bool    move_ptr ();
  13. bool    forwchar ();
  14. bool    wind_on_dot ();
  15. bool    backline ();
  16.  
  17. extern    char    MSG_mark_set[];
  18. extern    char    MSG_no_mark[];
  19. extern    char    MSG_go_b_n[];
  20. extern    char    MSG_bad_num[];
  21. #if RUNCHK
  22. extern    char    ERR_bas_1[];
  23. #endif
  24. extern    char    MSG_lX[];
  25. extern    char    MSG_lO[];
  26. extern    char    MSG_lD[];
  27.  
  28.  
  29. extern  bool    rplc_mode;
  30.  
  31. /*  pvr
  32. * Move cursor backwards. Do the
  33. * right thing if the count is less than
  34. * 0. Error if you try to move back from
  35. * the beginning of the buffer.
  36. */
  37. bool backchar (f, n, k)
  38. register int    n;
  39. {
  40.     if (n < 0)
  41.         return (forwchar (f, -n, KRANDOM));
  42.  
  43.     while (n--)
  44.     {
  45.         if (curwp -> w_unit_offset == 0)
  46.         {
  47.             if (!move_ptr (curwp,  -(long)R_B_PER_U(curwp),
  48.                 TRUE, TRUE, TRUE))
  49.                 return (FALSE);
  50.  
  51.             /* step to previous unit */
  52.             curwp -> w_unit_offset = R_CHR_PER_U(curwp) - 1;
  53.  
  54.             /* if before first line in window then move window */
  55.             wind_on_dot (curwp);
  56.         }
  57.         else
  58.             curwp -> w_unit_offset--;
  59.     }
  60.     curwp -> w_flag |= WFMODE;  /* update mode line */
  61.     return (TRUE);
  62. }
  63.  
  64. /*  pvr
  65. * Move cursor forwards. Do the
  66. * right thing if the count is less than
  67. * 0. Error if you try to move forward
  68. * from the end of the buffer.
  69. */
  70. bool forwchar (f, n, k)
  71. register int    n;
  72. {
  73.     if (n < 0)
  74.         return (backchar (f, -n, KRANDOM));
  75.  
  76.     curwp -> w_flag |= WFMODE;  /* update mode line */
  77.     while (n--)
  78.     {
  79.         if (curwp -> w_unit_offset >= (R_CHR_PER_U(curwp) - 1))
  80.         {
  81.             /* move to the mext unit */
  82.             curwp -> w_unit_offset = 0;
  83.  
  84.             if (!move_ptr (curwp,  (long)R_B_PER_U(curwp),
  85.                 TRUE, TRUE, TRUE))
  86.             {
  87.                 /* I am at the the end of the buffer */
  88.                 return (FALSE);
  89.             }
  90.  
  91.             /* if after the last line in window then move window */
  92.             wind_on_dot (curwp);
  93.         }
  94.         else if/* if at last byte of buffer then do not step  */
  95.         (DOT_POS(curwp) < BUF_SIZE(curwp))
  96.             curwp -> w_unit_offset++;/* step within unit */
  97.     }
  98.     return (TRUE);
  99. }
  100.  
  101. /*  pvr
  102. *   This function moves the specified pointer by the ammount specified
  103. *   in 'len'.   Move the dot pointer is 'dot' is true, else move
  104. *   the window pointer.  Do the fix up if 'fix' is TRUE.
  105. *   This is a relative move if 'rel' is TRUE, else it is an
  106. *   absolute move.
  107. */
  108.  
  109. bool    move_ptr (wp, len, dot, fix, rel)
  110. WINDOW  *wp;
  111. long    len;
  112. bool    dot, fix, rel;
  113. {
  114.     A32     cur_pos, dest_pos, fix_val, last_pos;
  115.     long    rel_pos;
  116.     A32     last_fixed_pos, align;
  117.     LINE    **line;
  118.     int     *l_off;
  119.     char    shift;
  120.     bool    no_limit;
  121.  
  122.     no_limit = TRUE;
  123.     if (dot)
  124.     {                       /* move dot position */
  125.         l_off = (int *)&wp -> w_doto;
  126.         line = &wp -> w_dotp;
  127.         align = R_SIZE(wp);  /* bytes -1 in a unit */
  128.     }
  129.     else
  130.     {                       /* move window position */
  131.         l_off = (int *)&wp -> w_loff;
  132.         line = &wp -> w_linep;
  133.         align = R_ALIGN(wp) - 1; /* interval of bytes to align window */
  134.     }
  135.  
  136.     /* get the current position in the buffer */
  137.     cur_pos = (*line) -> l_file_offset + *l_off;
  138.  
  139.     if (rel)
  140.     {
  141.         rel_pos = len;
  142.         dest_pos = len + cur_pos;   /* destination position */
  143.     }
  144.     else
  145.     {
  146.         rel_pos = len - cur_pos;   /* relative move amount */
  147.         dest_pos = len;   /* destination position */
  148.     }
  149.     if (fix)
  150.     {
  151.         shift = wp -> w_disp_shift;
  152.  
  153.         /* limit at begining */
  154.         if ((long)dest_pos < (long)shift)
  155.         {
  156.             rel_pos = shift - cur_pos;
  157.             no_limit = FALSE;
  158.         }
  159.         else
  160.         {
  161.             /* calculate fixed up destination position */
  162.             fix_val = dest_pos &= ~align;
  163.             fix_val += shift;
  164.  
  165.             /* calculate the last position in the buffer */
  166.             last_pos = BUF_SIZE(wp);
  167.             if (last_pos < (last_fixed_pos = (last_pos & ~align) + shift))
  168.                 last_pos = last_fixed_pos - align - 1;
  169.  
  170.             /* if we are going to limit at the end of the buffer */
  171.             if (last_pos < fix_val)
  172.             {
  173.                 fix_val = last_pos;
  174.                 no_limit = FALSE;
  175.             }
  176.             rel_pos = fix_val - cur_pos;
  177.         }
  178.     }
  179.     while (TRUE)
  180.     {
  181.         if (rel_pos < 0)       /* move  backward through buffer */
  182.         {
  183.             /* current line? */
  184.             if (*l_off + rel_pos >= 0)
  185.             {
  186.                 *l_off += (short) rel_pos;
  187.                 return (no_limit);
  188.             }
  189.             /* are we at the first line */
  190.             if ((*line) -> l_bp -> l_size != 0)
  191.             {               /* no, so step back */
  192.                 rel_pos += *l_off;
  193.                 (*line) = (*line) -> l_bp;/* move back one line */
  194.                 *l_off = (*line) -> l_used;
  195.             }
  196.             else
  197.             {               /* yes, limit at the begining */
  198.                 *l_off = 0;
  199.                 return (FALSE);
  200.             }
  201.         }
  202.         else /* move forward through buffer */
  203.         {
  204.             /* is in current line? */
  205.             if (((A32)(*l_off) + rel_pos) < ((A32)((*line) -> l_used)))
  206.             {
  207.                 *l_off += (short) rel_pos;
  208.                 return (no_limit);
  209.             }
  210.             if ((*line) -> l_fp -> l_size != 0)
  211.             {
  212.                 rel_pos -= (*line) -> l_used - *l_off;
  213.                 *l_off = 0;
  214.                 (*line) = (*line) -> l_fp;/* move forward one line */
  215.             }
  216.             else
  217.             {
  218.                 *l_off = (*line) -> l_used;/* at last line so limit it */
  219.                 return (FALSE);
  220.             }
  221.         }
  222.     }
  223.     return (TRUE);
  224. }
  225.  
  226. /*  pvr
  227. *   Move the window so that the dot is within it's
  228. *   area.   Return TRUE if window was moved.
  229. */
  230.  
  231. bool wind_on_dot (wp)
  232.  
  233. WINDOW * wp;
  234. {
  235.     long    diff, incr;
  236.     A32     d_offs, w_start, bytes, align;
  237.  
  238.     /* number of bytes in a row */
  239.     bytes = R_BYTES(wp);
  240.     /* number of bytes to align on */
  241.     align = R_ALIGN(wp);
  242.     /* offset of window from start of the buffer */
  243.     w_start = WIND_POS(wp);
  244.     /* offset of dot from start of the buffer */
  245.     d_offs = DOT_POS(wp);
  246.     /* calculate the amount to move that is 1/3 of the window */
  247.     incr = bytes * wp -> w_ntrows / 3;
  248.     /* if dot is before first line in window */
  249.     if ((diff = (d_offs - w_start)) < 0)/* diff used later */
  250.     {
  251.         move_ptr (wp, diff - incr, FALSE, TRUE, TRUE);
  252.         wp -> w_flag |= WFHARD;
  253.         return (TRUE);
  254.     }
  255.     /* if dot is after the last line in window */
  256.     if (0 < (diff -= (wp -> w_ntrows * bytes - 1)))
  257.     {
  258.         if (align != 1)
  259.             diff = (diff & ~(align - 1)) + align;
  260.         move_ptr (wp, diff + incr, FALSE, TRUE, TRUE);
  261.         wp -> w_flag |= WFHARD;
  262.         return (TRUE);
  263.     }
  264.     /* is window aligned? */
  265.     if (w_start != ((w_start & ~(align - 1)) + wp -> w_disp_shift))
  266.     {                       /* if no then move into alignment */
  267.         move_ptr (wp, 0L, FALSE, TRUE, TRUE);
  268.         wp -> w_flag |= WFHARD;
  269.         return (TRUE);
  270.     }
  271.     return (FALSE);
  272. }
  273.  
  274. /*  pvr
  275. * Go to the beginning of the
  276. * buffer. Setting WFHARD is conservative,
  277. * but almost always the case.
  278. */
  279. bool gotobob ()
  280. {
  281.     move_ptr (curwp, 0L, TRUE, TRUE, FALSE);    /* move dot */
  282.     move_ptr (curwp, 0L, FALSE, TRUE, FALSE);   /* move window */
  283.     curwp -> w_unit_offset = 0;
  284.     curwp -> w_flag |= WFHARD;
  285.     return (TRUE);
  286. }
  287.  
  288.  
  289. /*  pvr
  290. * Go to the end of the buffer.
  291. * Setting WFHARD is conservative, but
  292. * almost always the case.
  293. * Dot is one byte past the end of the buffer.
  294. */
  295. bool gotoeob ()
  296. {
  297.     move_ptr (curwp, BUF_SIZE(curwp), TRUE, TRUE, FALSE);  /* move dot */
  298.     curwp -> w_unit_offset = 0;
  299.     wind_on_dot (curwp);
  300.     return (TRUE);
  301. }
  302.  
  303.  
  304. /*  pvr
  305. * Move forward by full lines.
  306. * If the number of lines to move is less
  307. * than zero, call the backward line function to
  308. * actually do it. The last command controls how
  309. * the goal column is set.
  310. */
  311. bool forwline (f, n, k)
  312. {
  313.     if (n < 0)
  314.         return (backline (f, -n, KRANDOM));
  315.  
  316.     if (rplc_mode)
  317.     {
  318.         next_pat ();
  319.     }
  320.     else
  321.     {
  322.         /* move dot */
  323.         if (!move_ptr (curwp,  (long)R_BYTES(curwp) * n,
  324.             TRUE, TRUE, TRUE))
  325.             curwp -> w_unit_offset = 0;
  326.         wind_on_dot (curwp);
  327.         curwp -> w_flag |= WFMODE;  /* update mode line */
  328.     }
  329.     return (TRUE);
  330. }
  331.  
  332.  
  333. /*  pvr
  334. * This function is like "forwline", but
  335. * goes backwards. The scheme is exactly the same.
  336. * Check for arguments that are less than zero and
  337. * call your alternate. Figure out the new line and
  338. * call "movedot" to perform the motion.
  339. */
  340. bool backline (f, n, k)
  341. {
  342.     if (n < 0)
  343.         return (forwline (f, -n, KRANDOM));
  344.  
  345.     if (rplc_mode)
  346.     {
  347.         next_pat ();
  348.     }
  349.     else
  350.     {
  351.         if (!move_ptr (curwp,  -((long)(R_BYTES(curwp) * n)),
  352.             TRUE, TRUE, TRUE))
  353.             curwp -> w_unit_offset = 0;
  354.  
  355.         /* is dot before the top of window? */
  356.         wind_on_dot (curwp);
  357.         curwp -> w_flag |= WFMODE;  /* update mode line */
  358.     }
  359.     return (TRUE);
  360. }
  361.  
  362. /*  pvr
  363. * Scroll forward by a specified number
  364. * of lines, or by a full page if no argument.
  365. * (KRW) Added cursor (dot) weighting to force cursor
  366. *       to same position on new page.
  367. */
  368. bool forwpage (f, n, k)
  369. register int    n;
  370. {
  371.     long    mov_lines;
  372.  
  373.     if (rplc_mode)
  374.         next_pat ();
  375.     else
  376.     {
  377.         if (curwp -> w_ntrows <= 2)
  378.             mov_lines = 2;
  379.         else
  380.             mov_lines = curwp -> w_ntrows - 2;
  381.  
  382.         /* check if last line is already displayed */
  383.         if (WIND_POS(curwp) + (R_BYTES(curwp) * curwp -> w_ntrows) <
  384.             curwp -> w_bufp -> b_linep -> l_bp -> l_file_offset +
  385.             curwp -> w_bufp -> b_linep -> l_bp -> l_used)
  386.         {
  387.             move_ptr (curwp, (long)(R_BYTES(curwp) * mov_lines),
  388.                 FALSE, TRUE, TRUE);
  389.         }
  390.         /* move dot by same amount */
  391.         if (!move_ptr (curwp, (long)(R_BYTES(curwp) * mov_lines),
  392.             TRUE, TRUE, TRUE))
  393.             curwp -> w_unit_offset = 0;
  394.  
  395.         curwp -> w_flag |= WFHARD;
  396.     }
  397.     return (TRUE);
  398. }
  399.  
  400.  
  401. /*  pvr
  402. * This command is like "forwpage",
  403. * but it goes backwards. 
  404. */
  405. bool backpage (f, n, k)
  406. register int    n;
  407. {
  408.     long    mov_lines;
  409.  
  410.     if (rplc_mode)
  411.         next_pat ();
  412.     else
  413.     {
  414.         if (curwp -> w_ntrows <= 2)
  415.             mov_lines = 2;
  416.         else
  417.             mov_lines = curwp -> w_ntrows - 2;
  418.  
  419.         /* move window */
  420.         move_ptr (curwp, -(long)(R_BYTES(curwp) * mov_lines),
  421.             FALSE, TRUE, TRUE);
  422.         /* move dot by same amount */
  423.         if (!move_ptr (curwp, -(long)(R_BYTES(curwp) * mov_lines),
  424.             TRUE, TRUE, TRUE))
  425.             curwp -> w_unit_offset = 0;
  426.  
  427.         curwp -> w_flag |= WFHARD;
  428.     }
  429.     return (TRUE);
  430. }
  431.  
  432.  
  433. /*
  434. * Set the mark in the current window
  435. * to the value of dot. A message is written to
  436. * the echo line unless we are running in a keyboard
  437. * macro, when it would be silly.
  438. */
  439. bool setmark ()
  440. {
  441.  
  442.     if (curbp == blistp)        /* jam - hack to do goto/kill */
  443.         pickone ();
  444.     else
  445.     {
  446.         curwp -> w_markp = curwp -> w_dotp;
  447.         curwp -> w_marko = curwp -> w_doto;
  448.         if (kbdmop == NULL)
  449.         {
  450.             writ_echo (MSG_mark_set);
  451.         }
  452.     }
  453.     return (TRUE);
  454. }
  455.  
  456.  
  457. /*  pvr
  458. * Swap the values of "dot" and "mark" in
  459. * the current window. This is pretty easy, because
  460. * all of the hard work gets done by the standard routine
  461. * that moves the mark about. The only possible
  462. * error is "no mark".
  463. */
  464. bool swapmark ()
  465. {
  466.     register short  odoto;
  467.     register    LINE * odotp;
  468.  
  469.     if (curwp -> w_markp == NULL)
  470.     {
  471.         writ_echo (MSG_no_mark);
  472.         return (FALSE);
  473.     }
  474.  
  475.     odotp = curwp -> w_dotp;
  476.     curwp -> w_dotp = curwp -> w_markp;
  477.     curwp -> w_markp = odotp;
  478.     odoto = curwp -> w_doto;
  479.     curwp -> w_doto = curwp -> w_marko;
  480.     curwp -> w_marko = odoto;
  481.     wind_on_dot (curwp);
  482.     curwp -> w_flag |= WFMODE;  /* update mode line */
  483.     return (TRUE);
  484. }
  485.  
  486. /*  pvr
  487. * Go to a specific byte position in buffer.
  488. * If an argument is present, then
  489. * it is the byte number, else prompt for a byte number
  490. * to use.
  491. */
  492. bool gotoline (f, n, k)
  493. {
  494.     A32      index;
  495.     register int    s;
  496.     char    buf[32];
  497.  
  498.     if (f == FALSE)
  499.     {
  500.  
  501.         if ((s = ereply (MSG_go_b_n, buf, sizeof (buf), 0) != TRUE))
  502.             return (s);
  503.         switch (R_TYPE(curwp))
  504.         {
  505.         case TEXT:
  506.         case ASCII:
  507.         case EBCDIC:
  508.         case BINARY:
  509.         case HEX:
  510.             sscanf (buf, MSG_lX, &index);
  511.             break;
  512.         case OCTAL:
  513.             sscanf (buf, MSG_lO, &index);
  514.             break;
  515.         case DECIMAL:
  516.             sscanf (buf, MSG_lD, &index);
  517.             break;
  518. #if RUNCHK
  519.         default:
  520.             writ_echo (ERR_bas_1);
  521.             break;
  522. #endif
  523.         }
  524.     }
  525.  
  526.     if (n <= 0)
  527.     {
  528.         writ_echo (MSG_bad_num);
  529.         return (FALSE);
  530.     }
  531.  
  532.     move_ptr (curwp, index, TRUE, TRUE, FALSE);
  533.     curwp -> w_unit_offset = 0;
  534.  
  535.     curwp -> w_flag |= WFMODE;  /* update mode line */
  536.  
  537.     wind_on_dot (curwp);
  538.     return (TRUE);
  539. }
  540.  
  541.